/**
 * 1.javac Foo.java
 * 2.javap -c Foo
 *                       ┌─────────────┐
 *                       │             │                    ┌─────────┐
 *             ┌─────────│Throwable    │─────────┐          │         │
 *             │         └─────────────┘         │          │         │
 *             ▼                                 ▼          │ Checked │
 *       ┌───────────┐                     ┌───────────┐    │         │
 *       │ Exception │                     │ Error     │    │         │
 *       └───────────┘                     └───────────┘    └─────────┘
 *             │
 * ────────────┼──────────────────────────────────────────────────────────
 *             ▼
 *       ┌───────────┐                                      ┌─────────┐
 *       │ Runtime   │                                      │         │
 *       │ Exception │                                      │         │
 *       └───────────┘                                      │Unchecked│
 *                                                          │         │
 *                                                          │         │
 *                                                          └─────────┘
 */
//Classfile /Users/mike/workspace/git/knowledge/深入拆解java虚拟机/exception/src/main/java/Foo.class
//Last modified Aug 26, 2019; size 638 bytes
//    MD5 checksum 26b0c27c521bd577adaa54660a100da1
//    Compiled from "Foo.java"
//public class Foo
//  minor version: 0
//    major version: 55
//    flags: (0x0021) ACC_PUBLIC, ACC_SUPER
//    this_class: #7                          // Foo
//    super_class: #8                         // java/lang/Object
//    interfaces: 0, fields: 4, methods: 2, attributes: 1
//    Constant pool:
//    #1 = Methodref          #8.#23         // java/lang/Object."<init>":()V
//    #2 = Fieldref           #7.#24         // Foo.tryBlock:I
//    #3 = Fieldref           #7.#25         // Foo.finallyBlock:I
//    #4 = Class              #26            // java/lang/Exception
//    #5 = Fieldref           #7.#27         // Foo.catchBlock:I
//    #6 = Fieldref           #7.#28         // Foo.methodExit:I
//    #7 = Class              #29            // Foo
//    #8 = Class              #30            // java/lang/Object
//    #9 = Utf8               tryBlock
//    #10 = Utf8               I
//    #11 = Utf8               catchBlock
//    #12 = Utf8               finallyBlock
//    #13 = Utf8               methodExit
//    #14 = Utf8               <init>
//  #15 = Utf8               ()V
//      #16 = Utf8               Code
//      #17 = Utf8               LineNumberTable
//      #18 = Utf8               test
//      #19 = Utf8               StackMapTable
//      #20 = Class              #31            // java/lang/Throwable
//      #21 = Utf8               SourceFile
//      #22 = Utf8               Foo.java
//      #23 = NameAndType        #14:#15        // "<init>":()V
//      #24 = NameAndType        #9:#10         // tryBlock:I
//      #25 = NameAndType        #12:#10        // finallyBlock:I
//      #26 = Utf8               java/lang/Exception
//      #27 = NameAndType        #11:#10        // catchBlock:I
//      #28 = NameAndType        #13:#10        // methodExit:I
//      #29 = Utf8               Foo
//      #30 = Utf8               java/lang/Object
//      #31 = Utf8               java/lang/Throwable
//      {
//public Foo();
//    descriptor: ()V
//    flags: (0x0001) ACC_PUBLIC
//    Code:
//    stack=1, locals=1, args_size=1
//    0: aload_0
//    1: invokespecial #1                  // Method java/lang/Object."<init>":()V
//    4: return
//    LineNumberTable:
//    line 1: 0
//
//public void test();
//    descriptor: ()V
//    flags: (0x0001) ACC_PUBLIC
//    Code:
//    stack=2, locals=4, args_size=1
//    0: iconst_0
//    1: istore_1
//    2: iload_1
//    3: bipush        100
//    5: if_icmpge     75
//    8: aload_0
//    9: iconst_0
//    10: putfield      #2                  // Field tryBlock:I
//    13: iload_1
//    14: bipush        50
//    16: if_icmpge     27
//    19: aload_0
//    20: iconst_2
//    21: putfield      #3                  // Field finallyBlock:I
//    24: goto          69
//    27: iload_1
//    28: bipush        80
//    30: if_icmpge     41
//    33: aload_0
//    34: iconst_2
//    35: putfield      #3                  // Field finallyBlock:I
//    38: goto          75
//    41: aload_0
//    42: iconst_2
//    43: putfield      #3                  // Field finallyBlock:I
//    46: return
//    47: astore_2
//    48: aload_0
//    49: iconst_1
//    50: putfield      #5                  // Field catchBlock:I
//    53: aload_0
//    54: iconst_2
//    55: putfield      #3                  // Field finallyBlock:I
//    58: goto          69
//    61: astore_3
//    62: aload_0
//    63: iconst_2
//    64: putfield      #3                  // Field finallyBlock:I
//    67: aload_3
//    68: athrow
//    69: iinc          1, 1
//    72: goto          2
//    75: aload_0
//    76: iconst_3
//    77: putfield      #6                  // Field methodExit:I
//    80: return
//    Exception table:
//    from    to  target type
//    8    19    47   Class java/lang/Exception
//    27    33    47   Class java/lang/Exception
//    8    19    61   any
//    27    33    61   any
//    47    53    61   any
//    LineNumberTable:
//    line 8: 0
//    line 10: 8
//    line 11: 13
//    line 21: 19
//    line 12: 24
//    line 13: 27
//    line 21: 33
//    line 14: 38
//    line 21: 41
//    line 16: 46
//    line 18: 47
//    line 19: 48
//    line 21: 53
//    line 22: 58
//    line 21: 61
//    line 22: 67
//    line 8: 69
//    line 24: 75
//    line 25: 80
//    StackMapTable: number_of_entries = 7
//    frame_type = 252 /* append */
//    offset_delta = 2
//    locals = [ int ]
//    frame_type = 24 /* same */
//    frame_type = 13 /* same */
//    frame_type = 69 /* same_locals_1_stack_item */
//    stack = [ class java/lang/Exception ]
//    frame_type = 77 /* same_locals_1_stack_item */
//    stack = [ class java/lang/Throwable ]
//    frame_type = 7 /* same */
//    frame_type = 250 /* chop */
//    offset_delta = 5
//    }

/**
 * 这里有三个finalBlock块，一个位于try处，一个位于catch处，一个捕获try未捕获的或者是catch抛出的异常
 * Compiled from "Foo.java"
 * public class Foo {
 *   public Foo();
 *     Code:
 *        0: aload_0
 *        1: invokespecial #1                  // Method java/lang/Object."<init>":()V
 *        4: return
 *
 *   public void test();
 *     Code:
 *        0: iconst_0
 *        1: istore_1
 *        2: iload_1
 *        3: bipush        100
 *        5: if_icmpge     75
 *        8: aload_0
 *        9: iconst_0
 *       10: putfield      #2                  // Field tryBlock:I
 *       13: iload_1
 *       14: bipush        50
 *       16: if_icmpge     27
 *       19: aload_0
 *       20: iconst_2
 *       21: putfield      #3                  // Field finallyBlock:I
 *       24: goto          69
 *       27: iload_1
 *       28: bipush        80
 *       30: if_icmpge     41
 *       33: aload_0
 *       34: iconst_2
 *       35: putfield      #3                  // Field finallyBlock:I
 *       38: goto          75
 *       41: aload_0
 *       42: iconst_2
 *       43: putfield      #3                  // Field finallyBlock:I
 *       46: return
 *       47: astore_2
 *       48: aload_0
 *       49: iconst_1
 *       50: putfield      #5                  // Field catchBlock:I
 *       53: aload_0
 *       54: iconst_2
 *       55: putfield      #3                  // Field finallyBlock:I
 *       58: goto          69
 *       61: astore_3
 *       62: aload_0
 *       63: iconst_2
 *       64: putfield      #3                  // Field finallyBlock:I
 *       67: aload_3
 *       68: athrow
 *       69: iinc          1, 1
 *       72: goto          2
 *       75: aload_0
 *       76: iconst_3
 *       77: putfield      #6                  // Field methodExit:I
 *       80: return
 *     Exception table:
 *        from    to  target type
 *            8    19    47   Class java/lang/Exception
 *           27    33    47   Class java/lang/Exception
 *            8    19    61   any
 *           27    33    61   any
 *           47    53    61   any
 * }
 * 注意这里的Field finallyBlock:I出现了5次
 * 分别是if else if else catch 和最外层
 * 最外层catch了allexception（注意看Exception table）
 */

public class Foo {
    private int tryBlock;
    private int catchBlock;
    private int finallyBlock;
    private int methodExit;

    public void test() {
        for (int i = 0; i < 100; i++) {
            try {
                tryBlock = 0;
                if (i < 50) {
                    continue;
                } else if (i < 80) {
                    break;
                } else {
                    return;
                }
            } catch (Exception e) {
                catchBlock = 1;
            } finally {
                finallyBlock = 2;
            }
        }
        methodExit = 3;
    }
}